﻿using BaseUtils.Helper;
using DatabaseCore;
using DatabaseCore.Modal;
using DatabaseCore.Sqlite;
using DatabaseCore.Util;
using Service.src.Model.Folw;
using Service.src.NW.Enum;
using Service.src.NW.Model;
using Service.src.NW.Model.Enum;
using Service.src.NW.Model.Folw;
using Service.src.NW.Model.Folw.Database;
using System;
using System.Collections.Generic;

namespace Service.src.NW.Processor.Core
{
    public class DatabaseProcessor : BaseProcessor
    {
        internal static void Run(NodeProcessor nodeProcessor, NodeInputParam nodeInputParam)
        {

            NodeStatusEnum NodeStatus = NodeStatusEnum.ERROR;
            NodeDatabaseInputParam Database = nodeInputParam.Database;
            string SQL = null;
            bool AssertResult = Assert(nodeProcessor, Database, out SQL);
            if (!AssertResult)
            {
                Complete(nodeProcessor, NodeStatus);
                return;
            }
            SendNodeLoggerInfo(nodeProcessor, $"SQL: {SQL}", RuntimeErrorCodeEnum.SUCCESS);

            NodeStatus = NodeStatusEnum.SUCCESS;
            DBResult Result = new DBResult();
            try
            {
                Result = ExecuteSQL(SQL);
            }
            catch (Exception ex)
            {
                NodeStatus = NodeStatusEnum.ERROR;
                SendNodeLoggerError(nodeProcessor, $"执行数据库语句失败，原因：{ex.Message}");
            }
            SendNodeLoggerInfo(nodeProcessor, $"数据库执行结果 DBResult：{Result.ToJson()} ", RuntimeErrorCodeEnum.SUCCESS);
            nodeProcessor.NodeOutParam.SetOutParamValue<DBResult>(Result);
            Complete(nodeProcessor, NodeStatus);
        }

        public static DBResult ExecuteSQL(string SQL, int DatabaseId = 0)
        {
            if (DatabaseId == 0)
            {
                DatabaseId = SqliteHelper.SystemDefaultDBID;
            }
            if (!AppData.DatabaseCache.ContainsKey(DatabaseId))
            {
                throw new Exception($"数据库异常，无法找到数据库，请检查数据库连接是否正常,当前选择的数据库ID={DatabaseId}");
            }
            ParseSql PS = new ParseSql(SQL).GetOperation();
            if (PS.Operation == null)
            {
                throw new Exception($"SQL异常，请检查SQL语句，SQL={SQL}");
            }
            DBResult Result = new DBResult();
            DataSourceClient DataSource = AppData.DatabaseCache[DatabaseId];

            switch (PS.Operation)
            {
                case "INSERT":
                case "UPDATE":
                case "DELETE":
                case "ALTER":
                    int Num = DataSource.ExecuteSql(SQL);
                    Result.TotalCount = Num;
                    Result.Data = Num;
                    Result.Message = "受影响记录行数：" + Num;
                    break;
                case "SELECT":
                    Result = DataSource.QueryBySql(SQL);
                    break;
            }

            return Result;
        }

        private static bool Assert(NodeProcessor nodeProcessor, NodeDatabaseInputParam Database, out string SQL)
        {
            List<WhereParam> WhereParams = nodeProcessor.NodeInputParam.Database?.WhereParams;
            object[] pars = new object[0];
            if (WhereParams != null)
            {
                pars = new object[WhereParams.Count];
                for (int i = 0; i < WhereParams.Count; i++)
                {
                    object Value = GetNodeInputParamValue(nodeProcessor, WhereParams[i]);
                    pars[i] = Value;
                }
            }
            bool ass = true;
            if (Database == null || Database.DatabaseId < 0)
            {
                SendNodeLoggerError(nodeProcessor, $"数据库配置信息错误 ,未选择库ID", RuntimeErrorCodeEnum.NODE_INPUT_PARAM_NULL);
                ass = false;
            }

            if (string.IsNullOrEmpty(Database?.Sql))
            {
                SendNodeLoggerWarning(nodeProcessor, $"SQL不能为空 ", RuntimeErrorCodeEnum.NODE_INPUT_PARAM_NULL);
                ass = false;
            }
            SQL = "";
            if (ass)
            {
                SQL = string.Format(Database?.Sql, pars);
            }

            return ass;
        }
    }
}